#ifndef _aco_socket_h_
#define _aco_socket_h_

#include "sys/sock.h"

#ifdef __cplusplus
extern "C" {
#endif

// ==================================================
// Asynchronous Socket Type Definitions and Callback Prototypes
// ==================================================
#define invalid_aco_socket NULL

/**
 * @brief Asynchronous Socket handle (opaque type)
 * @note Internally encapsulates socket descriptor and related asynchronous operation state
 */
typedef void* aco_socket_t;

/**
 * @brief Accept connection completion callback
 * @param param User-defined parameter
 * @param code Operation result code (0 for success, negative for error)
 * @param tcp Newly established TCP connection socket
 * @param addr Source address information
 * @param addrlen Length of source address
 */
typedef void (*aco_onaccept)(void* param, int code, socket_t tcp, const struct sockaddr_storage* addr, socklen_t addrlen);

/**
 * @brief Connection establishment completion callback
 * @param param User-defined parameter
 * @param code Operation result code (0 for success, negative for error)
 * @param tcp Connected TCP socket
 * @param aco Associated coroutine socket object
 */
typedef void (*aco_onconnect)(void* param, int code);

/**
 * @brief Data reception completion callback
 * @param param User-defined parameter
 * @param code Operation result code (0 for success, negative for error)
 * @param bytes Number of bytes actually received
 */
typedef void (*aco_onrecv)(void* param, int code, size_t bytes);

/**
 * @brief Data transmission completion callback
 * @param param User-defined parameter
 * @param code Operation result code (0 for success, negative for error)
 * @param bytes Number of bytes actually sent
 */
typedef void (*aco_onsend)(void* param, int code, size_t bytes);

/**
 * @brief Datagram reception completion callback (connectionless)
 * @param param User-defined parameter
 * @param code Operation result code (0 for success, negative for error)
 * @param bytes Number of bytes actually received
 * @param addr Source address information
 * @param addrlen Length of source address
 */
typedef void (*aco_onrecvfrom)(void* param, int code, size_t bytes, 
                                     const struct sockaddr_storage* addr, socklen_t addrlen);

/**
 * @brief Datagram transmission completion callback (connectionless)
 * @param param User-defined parameter
 * @param code Operation result code (0 for success, negative for error)
 * @param bytes Number of bytes actually sent
 * @param addr Destination address information
 * @param addrlen Length of destination address
 */
typedef void (*aco_onsendto)(void* param, int code, size_t bytes, 
                                   const struct sockaddr_storage* addr, socklen_t addrlen);

/**
 * @brief Message reception completion callback with local/peer addresses
 * @param param User-defined parameter
 * @param code Operation result code (0 for success, negative for error)
 * @param bytes Number of bytes actually received
 * @param peer Peer socket address information
 * @param peerlen Length of peer address
 * @param local Local socket address information
 * @param locallen Length of local address
 */
typedef void (*aco_onrecvmsg)(void* param, int code, size_t bytes, 
                              const struct sockaddr_storage* peer, socklen_t peerlen,
                              const struct sockaddr_storage* local, socklen_t locallen);

/**
 * @brief Socket destruction completion callback
 * @param param User-defined parameter
 */
typedef void (*aco_ondestroy)(void* param);

// ==================================================
// Socket Pool Management Functions
// ==================================================

/**
 * @brief Initialize the asynchronous socket pool
 * @param initial_size Initial capacity of the socket pool
 * @note Must be called once at program startup before any socket operations
 */
void aco_socket_pool_init(size_t initial_size);

/**
 * @brief Destroy the asynchronous socket pool and release all resources
 * @note Should be called at program shutdown after all sockets are closed
 */ 
void aco_socket_pool_destroy(void);

// ==================================================
// Asynchronous Socket Operation Functions
// ==================================================

/**
 * @brief Create an asynchronous socket wrapper
 * @param socket Existing socket descriptor to wrap
 * @return aco_socket_t Opaque handle to the asynchronous socket
 * @return NULL if creation fails
 * @note The socket must be in non-blocking mode for proper asynchronous operation
 */
aco_socket_t aco_socket_create(socket_t socket);

/**
 * @brief Destroy an asynchronous socket
 * @param socket Asynchronous socket handle to destroy
 * @param ondestroy Optional callback invoked when destruction completes
 * @param param User parameter passed to the destruction callback
 * @return 0 on success, negative error code on failure
 * @note This is an asynchronous operation - the socket may not be immediately destroyed
 */
int aco_socket_destroy(aco_socket_t socket, aco_ondestroy ondestroy, void* param);

/**
 * @brief Asynchronously accept an incoming connection
 * @param socket Listening socket handle
 * @param onaccept Callback invoked when connection is accepted
 * @param param User parameter passed to the accept callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note The callback receives the new connected socket and associated async socket
 */
int aco_socket_accept(aco_socket_t socket, aco_onaccept onaccept, void* param);

/**
 * @brief Asynchronously connect to a remote address
 * @param socket Socket handle to use for connection
 * @param addr Remote address to connect to
 * @param addrlen Length of the remote address structure
 * @param onconnect Callback invoked when connection completes
 * @param param User parameter passed to the connect callback
 * @return 0 if operation initiated successfully, negative error code on failure
 */
int aco_socket_connect(aco_socket_t socket, const struct sockaddr_storage* addr, 
                              socklen_t addrlen, aco_onconnect onconnect, void* param);

/**
 * @brief Asynchronously receive data from a connected socket
 * @param socket Connected socket handle
 * @param buffer Buffer to store received data
 * @param bytes Maximum number of bytes to receive
 * @param timeout_ms Operation timeout in milliseconds (0 for no timeout)
 * @param onrecv Callback invoked when receive operation completes
 * @param param User parameter passed to the receive callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note For connection-oriented sockets (TCP) only
 */
int aco_socket_recv(aco_socket_t socket, void* buffer, size_t bytes, 
                          int timeout_ms, aco_onrecv onrecv, void* param);

/**
 * @brief Asynchronously send data to a connected socket
 * @param socket Connected socket handle
 * @param buffer Data buffer to send
 * @param bytes Number of bytes to send
 * @param onsend Callback invoked when send operation completes
 * @param param User parameter passed to the send callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note For connection-oriented sockets (TCP) only
 */
int aco_socket_send(aco_socket_t socket, const void* buffer, size_t bytes, 
                          aco_onsend onsend, void* param);

/**
 * @brief Asynchronously receive a datagram (connectionless)
 * @param socket Socket handle
 * @param buffer Buffer to store received data
 * @param bytes Maximum number of bytes to receive
 * @param onrecvfrom Callback invoked when receive operation completes
 * @param param User parameter passed to the receive callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note For connectionless sockets (UDP) only
 */
int aco_socket_recvfrom(aco_socket_t socket, void* buffer, size_t bytes, 
                                aco_onrecvfrom onrecvfrom, void* param);

/**
 * @brief Asynchronously send a datagram (connectionless)
 * @param socket Socket handle
 * @param addr Destination address
 * @param addrlen Length of destination address structure
 * @param buffer Data buffer to send
 * @param bytes Number of bytes to send
 * @param onsendto Callback invoked when send operation completes
 * @param param User parameter passed to the send callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note For connectionless sockets (UDP) only
 */
int aco_socket_sendto(aco_socket_t socket, const void* buffer, size_t bytes, 
                             const struct sockaddr_storage* addr, socklen_t addrlen, 
                             aco_onsendto onsendto, void* param);

/**
 * @brief Asynchronously receive data into multiple buffers (scatter input)
 * @param socket Connected socket handle
 * @param vec Array of buffer vectors
 * @param n Number of vectors in the array
 * @param onrecv Callback invoked when receive operation completes
 * @param param User parameter passed to the receive callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note Uses readv/recvmsg for efficient scatter input
 */
int aco_socket_recv_v(aco_socket_t socket, socket_bufvec_t* vec, int n, 
                             aco_onrecv onrecv, void* param);

/**
 * @brief Asynchronously send data from multiple buffers (gather output)
 * @param socket Connected socket handle
 * @param vec Array of buffer vectors
 * @param n Number of vectors in the array
 * @param onsend Callback invoked when send operation completes
 * @param param User parameter passed to the send callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note Uses writev/sendmsg for efficient gather output
 */
int aco_socket_send_v(aco_socket_t socket, socket_bufvec_t* vec, int n, 
                             aco_onsend onsend, void* param);

/**
 * @brief Asynchronously receive a datagram into multiple buffers
 * @param socket Socket handle
 * @param vec Array of buffer vectors
 * @param n Number of vectors in the array
 * @param onrecvfrom Callback invoked when receive operation completes
 * @param param User parameter passed to the receive callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note Vector version of recvfrom for connectionless sockets
 */
int aco_socket_recvfrom_v(aco_socket_t socket, socket_bufvec_t* vec, int n, 
                                 aco_onrecvfrom onrecvfrom, void* param);

/**
 * @brief Asynchronously send a datagram from multiple buffers
 * @param socket Socket handle
 * @param addr Destination address
 * @param addrlen Length of destination address structure
 * @param vec Array of buffer vectors
 * @param n Number of vectors in the array
 * @param onsendto Callback invoked when send operation completes
 * @param param User parameter passed to the send callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note Vector version of sendto for connectionless sockets
 */
int aco_socket_sendto_v(aco_socket_t socket, socket_bufvec_t* vec, int n, 
                               const struct sockaddr_storage* addr, socklen_t addrlen,
                               aco_onsendto onsendto, void* param);

// ==================================================
// Advanced Message Operations
// ==================================================

/**
 * @brief Asynchronously receive a message with ancillary data
 * @param socket Socket handle
 * @param buffer Buffer to store received data
 * @param bytes Maximum number of bytes to receive
 * @param onrecvmsg Callback invoked when receive operation completes
 * @param param User parameter passed to the receive callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note Supports receiving ancillary data and multiple addresses
 */
int aco_socket_recvmsg(aco_socket_t socket, void* buffer, size_t bytes, 
                              aco_onrecvmsg onrecvmsg, void* param);

/**
 * @brief Asynchronously send a message with ancillary data
 * @param socket Socket handle
 * @param peer Peer socket address
 * @param peerlen Length of peer address structure
 * @param local Local socket address (for packet info)
 * @param locallen Length of local address structure
 * @param buffer Data buffer to send
 * @param bytes Number of bytes to send
 * @param onsend Callback invoked when send operation completes
 * @param param User parameter passed to the send callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note Supports sending ancillary data and multiple addresses
 */
int aco_socket_sendmsg(aco_socket_t socket, const void* buffer, size_t bytes, 
                              const struct sockaddr_storage* peer, socklen_t peerlen,
                              const struct sockaddr_storage* local, socklen_t locallen,
                              aco_onsend onsend, void* param);

/**
 * @brief Asynchronously receive a message into multiple buffers with ancillary data
 * @param socket Socket handle
 * @param vec Array of buffer vectors
 * @param n Number of vectors in the array
 * @param onrecvmsg Callback invoked when receive operation completes
 * @param param User parameter passed to the receive callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note Vector version with support for ancillary data
 */
int aco_socket_recvmsg_v(aco_socket_t socket, socket_bufvec_t* vec, int n, 
                                aco_onrecvmsg onrecvmsg, void* param);

/**
 * @brief Asynchronously send a message from multiple buffers with ancillary data
 * @param socket Socket handle
 * @param peer Peer socket address
 * @param peerlen Length of peer address structure
 * @param local Local socket address (for packet info)
 * @param locallen Length of local address structure
 * @param vec Array of buffer vectors
 * @param n Number of vectors in the array
 * @param onsend Callback invoked when send operation completes
 * @param param User parameter passed to the send callback
 * @return 0 if operation initiated successfully, negative error code on failure
 * @note Vector version with support for ancillary data
 */
int aco_socket_sendmsg_v(aco_socket_t socket, socket_bufvec_t* vec, int n, 
                                const struct sockaddr_storage* peer, socklen_t peerlen,
                                const struct sockaddr_storage* local, socklen_t locallen,
                                aco_onsend onsend, void* param);


// ==================================================
// Event Processing
// ==================================================

/**
 * @brief Process asynchronous socket events
 * @param timeout Maximum time to wait for events (in milliseconds)
 * @return Number of events processed, or negative error code
 * @note This function should be called periodically to drive the async socket system
 */
int aco_socket_process(int timeout);

#ifdef __cplusplus
}
#endif

#endif // _aco_socket_h_

